package org.beetl.sql.core.db;

import org.beetl.sql.clazz.kit.KeyWordHandler;
import org.beetl.sql.clazz.kit.StringKit;
import org.beetl.sql.core.range.RangeSql;

import java.util.Map;

public class SqlServerStyle extends AbstractDBStyle {
    private SqlServerRange sqlServerRange = null;
    public SqlServerStyle() {
        this.keyWordHandler = new KeyWordHandler() {
            @Override
            public String getTable(String tableName) {
                return StringKit.addEscape(tableName,'[',']');
            }
            @Override
            public String getCol(String colName) {
                return StringKit.addEscape(colName,'[',']');
            }
        };
        sqlServerRange = new SqlServerRange(this);
    }



    @Override
    public String getDefaultSchema() {
        return "dbo";
    }


    @Override
    public String getName() {
        return "sqlserver";
    }


    @Override
    public final int getDBType() {
        return DBType.DB_SQLSERVER;
    }

    @Override
    public RangeSql getRangeSql() {
        return sqlServerRange;
    }

	@Override
	public boolean batchGeneratedKeysSupport(){
    	return false;
	}


    @Override
    public String getOrderBy() {
        //重写getOrderBy，如果设置了分页的order by条件 则按 order by 否则添加一个 current_timestamp 来排序
        return lineSeparator + appendExpress("text(' order by ' + _orderBy!'current_timestamp')" ) + " ";
    }

    static class SqlServerRange implements RangeSql {
        SqlServerStyle sqlServerStyle = null;
        public SqlServerRange(SqlServerStyle sqlServerStyle){
            this.sqlServerStyle = sqlServerStyle;
        }

        @Override
        public String toRange(String jdbcSql, Object objOffset, Long limit) {
            Long offset = ((Number)objOffset).longValue();
            offset = PageParamKit.sqlServerOffset(sqlServerStyle.offsetStartZero, offset);
            long pageEnd = PageParamKit.sqlServerPageEnd(offset, limit);

            jdbcSql = jdbcSql.replaceFirst("(?is)select(\\s+distinct\\s+)?", "$0 top(" + pageEnd + ") ");

            int capacity = jdbcSql.length() + 190;
            StringBuilder builder = new StringBuilder(capacity);
            builder.append("with query as ( select inner_query.*, row_number() over (order by current_timestamp) as beetl_rn from ( ");
            builder.append(jdbcSql);
            builder.append(" ) inner_query ) select * from query where beetl_rn between ");
            builder.append(offset).append(" and ").append(pageEnd);

            return builder.toString();
        }

        @Override
        public String toTemplateRange(Class mapping,String template) {
            return "with query as ( select inner_query.*, row_number() over (order by current_timestamp) as beetl_rn from ( "
                    + template.replaceFirst("(?is)select(\\s+distinct\\s+)?", "$0 top(" + sqlServerStyle.appendExpress(DBAutoGeneratedSql.PAGE_END )+ ") ") + sqlServerStyle.getOrderBy()
                    + " ) inner_query ) select * from query where beetl_rn between " + sqlServerStyle.appendExpress(DBAutoGeneratedSql.OFFSET ) + " and " + sqlServerStyle.appendExpress(DBAutoGeneratedSql.PAGE_END );
        }

        @Override
        public void addTemplateRangeParas(Map<String, Object> paras, Object objOffset, long size) {
            Long offset = (Long)objOffset;
            long s = offset + (sqlServerStyle.offsetStartZero ? 1 : 0);
            paras.put(DBAutoGeneratedSql.OFFSET, s);
            paras.put(DBAutoGeneratedSql.PAGE_END, s + size - 1);
        }
    }


}
